<?php
/**
 * User: @lose
 * Date: 2020/12/21
 * Time: 10:26 上午
 */

namespace Frieza\Modules\FlowPackage\Controllers;

use App\Http\Controllers\Controller;
use App\Pockets\GridDataModel as pGridDataModel;
use Doraemon\model\Flow\FlowPackage as mFlowPackage;
use Doraemon\model\NewTag\Tag as mTag;
use Doraemon\model\TopicActivity as mTopicActivity;
use Encore\Admin\Facades\Admin;
use Encore\Admin\Grid;
use Encore\Admin\Grid\Displayers\DropdownActions;
use Encore\Admin\Layout\Content;
use Encore\Admin\Widgets\Form;
use Frieza\Modules\FlowPackage\Actions\Delete;
use Frieza\Modules\FlowPackage\Actions\Finish;
use Illuminate\Http\Request;
use Doraemon\service\admin\FlowPackage as sFlowPackage;
use Illuminate\Support\MessageBag;
use Doraemon\service\WeeklyList as sWeeklyList;
use Doraemon\model\Topic\TopicActivity;
use Encore\Admin\Widgets\Table;

class FlowPackageController extends Controller
{
    public function index(Content $content, Request $request)
    {
        $where = $this->buildWhere($request->all());
        $page = $request->input('page', 1);
        $pageSize = $request->input('per_page', 15);
        $limit = [($page - 1) * $pageSize, $pageSize];
        $list = sFlowPackage::getList($where, $limit);
        $topicIdList = [];
        foreach ($list['list'] as &$info) {
            $info['ctr'] = '查看ctr';
            if($info['obj_type'] == mFlowPackage::OBJ_TYPE_TOPIC) {
                $topicIdList = array_merge($topicIdList, explode(',', $info['obj_value']));
            }
        }

        $topicList = [];
        if($topicIdList) {
            $topicList = mTopicActivity::select(['id', 'title'], ['id' => array_unique($topicIdList)]);
            $topicList = array_column($topicList, null, 'id');
        }

        return $content
            ->header('流量加油包')
            ->breadcrumb(['text' => '流量加油包'])
            ->row($this->_formatGrid($list, $topicList));
    }

    public function create(Content $content, Request $request, $packageId = 0)
    {
        $package = [];
        if($packageId) {
            $package = sFlowPackage::getInfoByPackageId($packageId);
            if($package['obj_type'] == mFlowPackage::OBJ_TYPE_ID) {
                $package['obj_id'] = $package['obj_value'];
            } else if($package['obj_type'] == mFlowPackage::OBJ_TYPE_TAG) {
                $package['obj_tag'] = $package['obj_value'];
            } else if ($package['obj_type'] == mFlowPackage::OBJ_TYPE_TOPIC) {
                $package['obj_topic_id'] = $package['obj_value'];
            } else if ($package['obj_type'] == mFlowPackage::OBJ_TYPE_WEEKLY) {
                $package['weekly_id'] = $package['obj_value'];
            } else if ($package['obj_type'] == mFlowPackage::OBJ_TYPE_USER) {
                $package['user_id'] = $package['obj_value'];
            } else if($package['obj_type'] == mFlowPackage::OBJ_TYPE_LIGHT_TYPE) {
                $package['light_topic_tag'] = $package['obj_value'];
            }
        }

        $form = $this->_formatForm($package);
        return $content
            ->header('加油包配置')
            ->breadcrumb(['text' => '流量加油包', 'url' => 'flowPackage'], ['text' => '加油包配置'])
            ->row($form);
    }

    public function save(Request $request)
    {
        try {
            $packageId = $request->input('id', 0);
            $data = [
                'title' => $request->input('title', ''),
                'obj_type' => $request->input('obj_type', ''),
                'obj_value' => $request->input('obj_value', ''),
                'flow_type' => $request->input('flow_type', ''),
                'target_exposure' => $request->input('target_exposure', 0),
                'start_time' => $request->input('start_time', ''),
                'end_time' => $request->input('end_time', ''),
                'department' => $request->input('department'),
                'weight' => $request->input('weight', 0),
                'admin_id' => Admin::user()->id,
                'pos' => $request->input('pos'),
            ];

            if ($data['flow_type'] == mFlowPackage::FLOW_TYPE_PACKAGE && $data['target_exposure'] == 0) {
                throw new \Exception('目标曝光量无效');
            }

            if($data['start_time'] > $data['end_time']) {
                throw new \Exception('开始时间不能大于结束时间');
            }

            if($data['obj_type'] == mFlowPackage::OBJ_TYPE_ID) {
                $data['obj_value'] = $request->input('obj_id', '');
            } else if($data['obj_type'] == mFlowPackage::OBJ_TYPE_TAG) {
                $data['obj_value'] = implode(',', array_unique(array_filter($request->input('obj_tag', []))));
            } else if ($data['obj_type'] == mFlowPackage::OBJ_TYPE_TOPIC) {
                $data['obj_value'] = implode(',', array_unique($request->input('obj_topic_id', [])));
            } else if($data['obj_type'] == mFlowPackage::OBJ_TYPE_WEEKLY) {
                $data['obj_value'] = $request->input('weekly_id', '');
            } else if ($data['obj_type'] == mFlowPackage::OBJ_TYPE_USER) {
                $data['obj_value'] = $request->input('user_id', '');
            } else if($data['obj_type'] == mFlowPackage::OBJ_TYPE_LIGHT_TYPE) {
                $data['obj_value'] = implode(',', array_unique(array_filter($request->input('light_topic_tag', []))));
            }

            if($data['obj_type'] != mFlowPackage::OBJ_TYPE_WEEKLY) {
                if(!$data['obj_value']) {
                    throw new \Exception('您还没有填写曝光内容');
                }
            }

            if($data['obj_type'] == mFlowPackage::OBJ_TYPE_ID) {
                if(!preg_match("/^[A-Za-z0-9,]+$/u", $data['obj_value'])) {
                    throw new \Exception('请输入用,分隔的id');
                }

                $data['obj_value'] = implode(',', array_unique(explode(',', $data['obj_value'])));
            }

            if($data['obj_type'] == mFlowPackage::OBJ_TYPE_USER) {
                if(!preg_match("/^[0-9,]+$/u", $data['obj_value'])) {
                    throw new \Exception('请输入用,分隔的id');
                }

                $data['obj_value'] = implode(',', array_unique(explode(',', $data['obj_value'])));
            }

            $packageId = sFlowPackage::save($packageId, $data, $request->input('user_profile'));

            if($packageId) {
                return redirect(url("/admin/flowPackage"));
            } else {
                throw new \Exception('添加失败');
            }
        } catch (\Exception $e) {
            $error = new MessageBag([
                'title' => $e->getMessage()
            ]);
            return back()->with(compact('error'))->withInput();
        }
    }

    public function sort(Request $request)
    {
        $sort = $request->input('sort');
        sFlowPackage::saveSort($sort);
    }

    public function delete(Request $request)
    {
        $packageId = $request->input('_key');
        try {
            sFlowPackage::saveStatusByPackageId($packageId, mFlowPackage::STATUS_DELETE);
            $type = 'success';
            $content = '删除成功';
        } catch (\Exception $e) {
            $type = 'error';
            $content = $e->getMessage();
        }

        return response()->json($this->getResponse($type, $content));
    }

    public function finish(Request $request)
    {
        $packageId = $request->input('_key');
        try {
            sFlowPackage::saveStatusByPackageId($packageId, mFlowPackage::STATUS_FINISH);
            $type = 'success';
            $content = '终止成功';
        } catch (\Exception $e) {
            $type = 'error';
            $content = $e->getMessage();
        }

        return response()->json($this->getResponse($type, $content));
    }

    private function getResponse($type, $content)
    {
        return [
            'status' => true,
            'then' => [
                'action' => 'refresh',
                'value'  => true,
            ],
            'toastr' => [
                'type' => $type,
                'content' => $content,
                'options' => [
                    'positionClass' => 'toast-top-center'
                ]
            ]
        ];
    }

    private function _formatForm($package)
    {
        $processing = 0;
        if($package['start_time'] < date('Y-m-d H:i:s') && $package['end_time'] > date('Y-m-d H:i:s')) {
            $processing = 1;
        }
        $form = new Form($package);
        $form->hidden('id');
        $form->text('title', '曝光主题')->required();
        $form->radio('pos', '曝光位置')->options(mFlowPackage::POS_DESC)->default(mFlowPackage::POS_RECOMMEND_FEED)->required();
        $tagList = mTag::select(['id', 'tag'], ['tag_status' => mTag::STATUS_NORMAL]);
        $select = [];
        if($tagList) {
            foreach ($tagList as $info) {
                $select[$info['tag']] = $info['tag'];
            }
        }

        $lightTopicList = TopicActivity::select(['id', 'title'], ['status' => TopicActivity::STATUS_SUCCESS]);
        $lightTopicSelect = [];
        if($lightTopicList) {
            foreach ($lightTopicList as $info) {
                $lightTopicSelect[$info['title']] = $info['title'];
            }
        }

        $topicList = mTopicActivity::select(['id', 'title'], ['status' => mTopicActivity::STATUS_SUCCESS]);
        $topicSelect = [];
        if($topicList) {
            foreach ($topicList as $tagInfo) {
                $topicSelect[$tagInfo['id']] = $tagInfo['title'];
            }
        }

        if($processing) {
            $form->radio('flow_type', '策略类型')
                ->options([$package['flow_type'] => mFlowPackage::FLOW_TYPE_DESC[$package['flow_type']]])->required();
            if ($package['flow_type'] == mFlowPackage::FLOW_TYPE_PACKAGE) {
                $form->number('target_exposure', '目标曝光量')->width(200);
            }
            $form->radio('obj_type', '内容类型')->readonly()->default(mFlowPackage::OBJ_TYPE_TOPIC)
                ->options(mFlowPackage::OBJ_TYPE_DESC)
                ->when(mFlowPackage::OBJ_TYPE_TOPIC, function (Form $form) use($topicSelect, $package) {
                    $form->multipleSelect('obj_topic_id', '话题id')->options($topicSelect)->default($package['obj_topic_id'])->readonly();
                })->when(mFlowPackage::OBJ_TYPE_TAG, function (Form $form) use($select, $package) {
                    $form->multipleSelect('obj_tag', '标签')->options($select)->default($package['obj_tag'])->readonly();
                })->when(mFlowPackage::OBJ_TYPE_ID, function (Form $form) {
                    $form->text('obj_id', '内容id')->placeholder('请输入内容id,多个用英文逗号(,)隔开')->readonly();
                })->when(mFlowPackage::OBJ_TYPE_WEEKLY, function (Form $form) {
                    $form->radio('weekly_id', '周榜类型')->options(sWeeklyList::CLASS_MAP)->readonly();
                })->when(mFlowPackage::OBJ_TYPE_USER, function (Form $form) {
                    $form->textarea('user_id', '用户内容')->placeholder('请输入用户uid,多个用英文逗号(,)隔开')->readonly();
                })->when(mFlowPackage::OBJ_TYPE_LIGHT_TYPE, function (Form $form) use($lightTopicSelect, $package) {
                    $form->multipleSelect('light_topic_tag', '轻话题')->options($lightTopicSelect)->default($package['obj_tag'])->readonly();
                });
            $form->datetime('start_time', '开始时间')->required()->help('曝光时间开始后不可修改')->readonly();
            $form->datetime('end_time', '结束时间')->required()->help('曝光时间开始后不可修改');
            $form->radio('department', '所属业务')->readonly()->default(mFlowPackage::DEPARTMENT_DOC)
                ->options(mFlowPackage::DEPARTMENT_DESC)
                ->when('!=', mFlowPackage::DEPARTMENT_BUSINESS_SELL, function (Form $form) {
                    $form->text('weight', '权重')->help('数字越大权重越高，建议从0-10中的正整数挑')->readonly();
                })->required()->readonly();
        } else {
            $form->radio('flow_type', '策略类型')->default(mFlowPackage::FLOW_TYPE_PACKAGE)
                ->options(mFlowPackage::FLOW_TYPE_DESC)
                ->when(mFlowPackage::FLOW_TYPE_PACKAGE, function (Form $form) {
                    $form->number('target_exposure', '目标曝光量')->width(200);
                })->required();
            $form->radio('obj_type', '内容类型')
                ->options(mFlowPackage::OBJ_TYPE_DESC)->default(mFlowPackage::OBJ_TYPE_TOPIC)
                ->when(mFlowPackage::OBJ_TYPE_TOPIC, function (Form $form) use($topicSelect) {
                    $form->multipleSelect('obj_topic_id', '话题id')->options($topicSelect);
                })->when(mFlowPackage::OBJ_TYPE_TAG, function (Form $form) use($select) {
                    $form->multipleSelect('obj_tag', '标签')->options($select);
                })->when(mFlowPackage::OBJ_TYPE_ID, function (Form $form) {
                    $form->text('obj_id', '内容id')->placeholder('请输入内容id,多个用英文逗号(,)隔开');
                })->when(mFlowPackage::OBJ_TYPE_WEEKLY, function (Form $form) {
                    $form->radio('weekly_id', '周榜类型')->options(sWeeklyList::CLASS_MAP);
                })->when(mFlowPackage::OBJ_TYPE_USER, function (Form $form) {
                    $form->textarea('user_id', '用户内容')->placeholder('请输入用户uid,多个用英文逗号(,)隔开');
                })->when(mFlowPackage::OBJ_TYPE_LIGHT_TYPE, function (Form $form) use($lightTopicSelect, $package) {
                    $form->multipleSelect('light_topic_tag', '轻话题')->options($lightTopicSelect);
                });
            $form->datetime('start_time', '开始时间')->required()->help('曝光时间开始后不可修改');
            $form->datetime('end_time', '结束时间')->required()->help('曝光时间开始后不可修改');
            $form->radio('department', '所属业务')->default(mFlowPackage::DEPARTMENT_DOC)
                ->options(mFlowPackage::DEPARTMENT_DESC)
                ->when('!=', mFlowPackage::DEPARTMENT_BUSINESS_SELL, function (Form $form) {
                    $form->text('weight', '权重')->help('数字越大权重越高，建议从0-10中的正整数挑')->rules('required')->pattern('^([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$');
                })->required();
        }
        $form->fieldset('分群区', function (Form $form) {
            $form->userProfile('user_profile', '用户分群')->generate();
        });
        $form->action('/admin/flowPackage/save');
        return $form;
    }

    private function _formatGrid($list, $topicList)
    {
        $gridModel = new pGridDataModel($list['list'], $list['total']);
        return Admin::grid($gridModel,
            function (Grid $grid) use($topicList) {
                $grid->paginate(15);
                $grid->setActionClass(DropdownActions::class);
                $grid->filter(function (Grid\Filter $filter) {
                    $filter->disableIdFilter();
                    $filter->column(1 / 2, function (Grid\Filter $filter) {
                        $filter->equal('title', '标题')->placeholder('根据名称模糊匹配');
                        $filter->between('time', '开始时间')->datetime();
                        $filter->equal('department', '所属业务')->select(mFlowPackage::DEPARTMENT_DESC);
                    });
                    $filter->column(1 / 2, function (Grid\Filter $filter) {
                        $filter->equal('flow_type', '策略类型')->select(mFlowPackage::FLOW_TYPE_DESC);
                        $filter->equal('obj_type', '内容类型')->select(mFlowPackage::OBJ_TYPE_DESC);

                    });
                });

                $grid->disableExport();
                $grid->disableRowSelector();

                $grid->column('id', 'ID')->help('拖动箭头可排序')->sort('flowPackage/sort');
                $grid->column('flow_type', '策略类型')->display(function () {
                    return mFlowPackage::FLOW_TYPE_DESC[$this->flow_type];
                })->label([
                    mFlowPackage::FLOW_TYPE_PACKAGE => 'primary',
                    mFlowPackage::FLOW_TYPE_QUEUE => 'info',
                ]);
                $grid->column('title', '主题');
                $grid->column('obj_type', '内容类型')->display(function () {
                    return mFlowPackage::OBJ_TYPE_DESC[$this->obj_type];
                });

                $grid->column('', '内容值')->modal('内容值', function () use ($topicList) {
                    $res =  $this->obj_value;
                    if($this->obj_type == mFlowPackage::OBJ_TYPE_TOPIC) {
                        $topicIdList = explode(',', $this->obj_value);
                        $topicTitle = [];
                        foreach ($topicIdList as $topicId) {
                            if(isset($topicList[$topicId])) {
                                $topicTitle[] = "id:{$topicId} 名称:{$topicList[$topicId]['title']}";
                            }
                        }
                        $res =  implode(',', $topicTitle);
                    } else if($this->obj_type == mFlowPackage::OBJ_TYPE_WEEKLY) {
                        $res =  sWeeklyList::CLASS_MAP[$this->obj_value];
                    }


                    return new Table([], ['内容信息' => $res]);
                });
                $grid->column('pos', '曝光位置')->display(function () {
                    return mFlowPackage::POS_DESC[$this->pos];
                });
                $grid->column('department', '所属业务')->display(function () {
                    return mFlowPackage::DEPARTMENT_DESC[$this->department];
                });
                $grid->column('weight', '权重')->help('数值越小权重越大，默认为0，可在提交前自行选择其他数值');
                $grid->column('start_time', '曝光时间')->display(function () {
                    return "开始{$this->start_time}<br/>结束{$this->end_time}";
                });
                $grid->column('package_status', '状态')->display(function () {
                    $status = '';
                    $currentTime = date("Y-m-d H:i:s");
                    if ($currentTime < $this->start_time) {
                        $status = '未开始';
                    } else if ($currentTime > $this->start_time && $currentTime < $this->end_time) {
                        $status =  '进行中';
                    } else if ($currentTime > $this->end_time) {
                        $status =  '已结束';
                    }
                    if($this->package_status == mFlowPackage::STATUS_FINISH) {
                        $status = mFlowPackage::STATUS_DESC[$this->package_status];
                    }
                    return $status;
                });
                $grid->column('real_exposure', '曝光量')->display(function () {
                    $targetExposure = '-';
                    if ($this->flow_type == mFlowPackage::FLOW_TYPE_PACKAGE) {
                        $targetExposure = $this->target_exposure;
                    }


                    if ($this->flow_type == mFlowPackage::FLOW_TYPE_QUEUE) {
                        $realExposure = $this->real_exposure;
                    } else {
                        // 实际曝光量 / 目标曝光量
                        // 当实际曝光量或者目标曝光量都没有时，没有计算的必要
                        if(!$this->real_exposure || !$this->target_exposure) {
                            $realExposure = 0 . '(0%)';
                        } else {
                            // 当类型为扶持队列时，也没必要计算
                            $percentage = round(($this->real_exposure / $this->target_exposure) * 100, 2);
                            $realExposure =  $this->real_exposure . "({$percentage}%)";
                        }
                    }


                    return "目标曝光量 $targetExposure <br/>当前曝光量  $realExposure";

                });
                $grid->column('addtime', '创建时间')->display(function () {
                    $addtime = $this->addtime;
                    $name = Admin::user()->find($this->admin_id)->name;
                    return "创建时间：$addtime <br/> 最后操作人：$name";
                });
                $grid->column('ctr', 'ctr')->link(function () {
                    $startTime = date('Ymd', strtotime($this->start_time));
                    $endTime = date('Ymd', strtotime($this->end_time));
                    if ($this->flow_type == mFlowPackage::FLOW_TYPE_QUEUE) {
                        return "https://metabase.haohaozhu.me/question/2227?suggestsign=support_queue_recall_{$this->id}&start_day={$startTime}&end_day={$endTime}";
                    } else {
                        return "https://metabase.haohaozhu.me/question/2227?suggestsign=add_expose_package_recall_{$this->id}&start_day={$startTime}&end_day={$endTime}";
                    }
                });
                $grid->column('user_profile', '分群信息')->userProfile();

                $grid->actions(function (Grid\Displayers\Actions $actions) {
                    $actions->disableDelete();
                    if($actions->row->package_status == mFlowPackage::STATUS_FINISH) {
                        $actions->disableEdit();
                        $actions->disableView();
                    } else {
                        if($actions->row->start_time > date('Y-m-d H:i:s')) {
                            $actions->disableView();
                            $actions->add(new Delete);
                        }

                        if($actions->row->start_time < date('Y-m-d H:i:s') && $actions->row->end_time > date('Y-m-d H:i:s')) {
                            $actions->disableView();
                            $actions->add(new Finish);
                        }

                        if($actions->row->end_time < date('Y-m-d H:i:s')) {
                            $actions->disableView();
                            $actions->disableEdit();
                        }
                    }
                });
            }
        );
    }

    private function buildWhere($params)
    {
        $where = [];
        $where['package_status[!]'] = mFlowPackage::STATUS_DELETE;
        if(isset($params['title']) && $params['title']) {
            $where['title[~]'] = $params['title'];
        }

        if(isset($params['obj_type']) && $params['obj_type']) {
            $where['obj_type'] = $params['obj_type'];
        }

        if(isset($params['flow_type']) && $params['flow_type']) {
            $where['flow_type'] = $params['flow_type'];
        }

        if(isset($params['department']) && $params['department']) {
            $where['department'] = $params['department'];
        }

        if(isset($params['time']['start']) && $params['time']['start']) {
            $where['start_time[>=]'] = $params['time']['start'];
        }

        if(isset($params['time']['end']) && $params['time']['end']) {
            $where['end_time[<=]'] = $params['time']['end'];
        }

        return $where;
    }
}